home *** CD-ROM | disk | FTP | other *** search
- /*
- Modal Dialog TextEdit useritem snippet
- Steve Falkenburg-- MacDTS
-
- This snippet shows the steps necessary to implement a scrolling, editable text field
- in a dialog. You may want to do this if you will be requiring the user to enter more than
- 255 characters (the limit for editText items), if you want a different font for several
- different editText items, or it you want to add scrolling support to an editible text item.
- */
-
-
- // constants
-
- #define kMyDialog 128
- #define kInFront (WindowPtr)-1L
- #define kEditTextItem 2
- #define kScrollerItem 3
- #define kMargin 4
- #define kPageLines 16
- #define kScrollToTop 0
- #define kScrollToBottom 1
- #define kMaxLines 128
- #define kCheckOneItem 5
- #define kCheckTwoItem 6
-
- // prototypes
-
- void main(void);
- void InitStuff(void);
- void DoDialog(void);
- void SetupDialog(DialogPtr theDialog);
- void PrepareFreeDialog(DialogPtr theDialog);
-
- pascal void EditTextDrawProc(DialogPtr theDialog,short theItem);
- pascal Boolean MyDialogFilter(DialogPtr theDialog,EventRecord *ev,short *itemHit);
- void HandleKeyPress(DialogPtr theDialog,char theChar);
- void HandleIdle(DialogPtr theDialog);
- void HandleActivate(DialogPtr theDialog);
- Boolean HandleMouse(DialogPtr theDialog,Point pt,short modifiers);
-
- void HandleScroller(DialogPtr theDialog,Point pt);
- pascal void ScrollBarAction(ControlHandle theControl,short part);
- void ScrollText(DialogPtr theDialog,short lines);
- void ReAlignTextToScrollbar(DialogPtr theDialog);
- void ReAlignScrollbarToText(DialogPtr theDialog);
-
- pascal Boolean MyTEClickProc(void);
-
- ControlHandle GetScrollBar(DialogPtr theDialog);
- TEHandle GetTEHandle(DialogPtr theDialog);
-
-
- /* main entry point */
-
- void main(void)
- {
- InitStuff();
- DoDialog();
- ExitToShell();
- }
-
-
- /* initialize the Mac managers */
-
- void InitStuff(void)
- {
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
- FlushEvents(everyEvent,0);
- }
-
-
- /* display dialog, and handle pretty standard ModalDialog loop. The modal dialog loop doesn't
- handle item hits to the scroll bar or text items. These are handled through the filter
- procedure
- */
-
- void DoDialog(void)
- {
- DialogPtr theDialog;
- short item;
- ControlHandle checkBoxControl;
- short iType;
- Rect iRect;
-
- theDialog = GetNewDialog(kMyDialog,nil,kInFront);
- SetupDialog(theDialog);
-
- do {
- ModalDialog(MyDialogFilter,&item);
- switch (item) {
- case kCheckOneItem: // check boxes
- case kCheckTwoItem:
- GetDItem(theDialog,item,&iType,&checkBoxControl,&iRect);
- SetCtlValue(checkBoxControl,!GetCtlValue(checkBoxControl));
- break;
- }
- } while (item!=ok);
-
- PrepareFreeDialog(theDialog);
- DisposeDialog(theDialog);
- }
-
-
- /* Creates the necessary data structures necessary to use the textedit item in our dialog. A
- handle to the TextEdit record is stored in the Dialog's window refCon field.
- */
-
- void SetupDialog(DialogPtr theDialog)
- {
- short iType;
- Handle iHndl;
- Rect iRect;
- ControlHandle theControl;
- short fontNum;
- TEHandle theTE;
-
- SetPort(theDialog);
-
- GetDItem(theDialog,kScrollerItem,&iType,&theControl,&iRect); // set up the scroll bar
- SetCtlMin(theControl,0); // (it's stored in a CNTL)
- SetCtlMax(theControl,kMaxLines);
-
- GetDItem(theDialog,kEditTextItem,&iType,&iHndl,&iRect);
- SetDItem(theDialog,kEditTextItem,iType,EditTextDrawProc,&iRect);
-
- InsetRect(&iRect,kMargin,kMargin);
-
- GetFNum("\pgeneva",&fontNum);
- TextFont(fontNum);
- theTE = TENew(&iRect,&iRect); // create our textedit item
- GetFNum("\pchicago",&fontNum);
- TextFont(fontNum);
-
- SetClikLoop(MyTEClickProc,theTE); // callback for drag-scrolling
- TEAutoView(true,theTE); // turn auto-scroll on for text entry
-
- SetWRefCon(theDialog,(long)theTE);
- }
-
-
-
- /* free the memory taken by the textedit record before closing the dialog
- */
-
- void PrepareFreeDialog(DialogPtr theDialog)
- {
- TEHandle theTE;
-
- theTE = GetTEHandle(theDialog);
- TEDispose(theTE);
- }
-
-
- /* dialog user item draw procedure for text box. It just calls FrameRect
- */
-
- pascal void EditTextDrawProc(DialogPtr theDialog,short theItem)
- {
- short iType;
- Handle iHndl;
- Rect iRect;
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(theDialog);
-
- GetDItem(theDialog,theItem,&iType,&iHndl,&iRect);
- FrameRect(&iRect);
-
- SetPort(savePort);
- }
-
-
- /* this is the main dispatcher for events to be passed off to the scroll bar or textedit box.
- looks sort of like a WaitNextEvent event handler.
- */
-
- pascal Boolean MyDialogFilter(DialogPtr theDialog,EventRecord *ev,short *itemHit)
- {
- char theChar;
-
- switch (ev->what) {
- case keyDown:
- case autoKey:
- theChar = (ev->message & charCodeMask);
- HandleKeyPress(theDialog,theChar);
- return true;
- case nullEvent:
- HandleIdle(theDialog);
- return false;
- case activateEvt:
- HandleActivate(theDialog);
- return false;
- case mouseDown:
- return HandleMouse(theDialog,ev->where,ev->modifiers);
- default:
- return false;
- }
- }
-
-
- /* dialog filter event handler for keypresses. All keypresses are passed to the textedit box
- */
-
- void HandleKeyPress(DialogPtr theDialog,char theChar)
- {
- TEHandle theTE;
-
- theTE = GetTEHandle(theDialog);
- TEKey(theChar,theTE);
- ReAlignScrollbarToText(theDialog);
- }
-
-
- /* handler for null events. used in our case to blink the insertion point
- */
-
- void HandleIdle(DialogPtr theDialog)
- {
- TEHandle theTE;
-
- theTE = GetTEHandle(theDialog);
- TEIdle(theTE);
- }
-
-
- /* activate event handler. we take this opportunity to call TEActivate to activate the textedit
- box
- */
-
- void HandleActivate(DialogPtr theDialog)
- {
- TEHandle theTE;
-
- theTE = GetTEHandle(theDialog);
- TEActivate(theTE);
- }
-
-
- /* mouse-down hander. here, we see if the mousedown was in the scrollbar or in the textedit
- record. if in the textedit item, we call teclick. If in the scrollbar, we call handlescroller
- to do further processing
- */
-
- Boolean HandleMouse(DialogPtr theDialog,Point pt,short modifiers)
- {
- short iType;
- Handle iHndl;
- Rect textRect,scrollerRect;
- TEHandle theTE;
- GrafPtr savePort;
- Boolean shiftDown,result;
- ControlHandle theControl;
- short part;
-
- GetPort(&savePort);
- SetPort(theDialog);
-
- shiftDown = modifiers & shiftKey;
- GlobalToLocal(&pt);
-
- GetDItem(theDialog,kEditTextItem,&iType,&iHndl,&textRect);
- GetDItem(theDialog,kScrollerItem,&iType,&iHndl,&scrollerRect);
-
- if (PtInRect(pt,&textRect)) {
- theTE = GetTEHandle(theDialog);
- TEClick(pt,shiftDown,theTE);
- result = true;
- }
- else if (PtInRect(pt,&scrollerRect)) {
- HandleScroller(theDialog,pt);
- result = true;
- }
- else
- result = false;
-
- SetPort(savePort);
-
- return result;
- }
-
-
- /* here, we see which part of the scrollbar was clicked in by calling findcontrol. trackcontrol
- is then called with the appropriate action proc if in one of the buttons or page areas. if
- in the thumb, the text is simply re-aligned to the new scrollbar position
- */
-
- void HandleScroller(DialogPtr theDialog,Point pt)
- {
- short part;
- ControlHandle theControl;
-
- part = FindControl(pt,theDialog,&theControl);
- switch (part) {
- case inUpButton:
- case inDownButton:
- case inPageUp:
- case inPageDown:
- TrackControl(theControl,pt,ScrollBarAction);
- break;
- case inThumb:
- TrackControl(theControl,pt,nil);
- ReAlignTextToScrollbar(theDialog);
- break;
- }
- }
-
-
- /* trackcontrol callback used to determine which direction to scroll the text, and by how much.
- once this is known, the text is scrolled, and the scrollbar adjusted.
- */
-
- pascal void ScrollBarAction(ControlHandle theControl,short part)
- {
- DialogPtr theDialog;
- short lines;
- short ctlValue,ctlMax,ctlMin;
-
- ctlMax = GetCtlMax(theControl);
- ctlMin = GetCtlMin(theControl);
- ctlValue = GetCtlValue(theControl);
-
- theDialog = (*theControl)->contrlOwner;
-
- switch (part) {
- case inUpButton:
- lines = -1;
- break;
- case inDownButton:
- lines = 1;
- break;
- case inPageUp:
- lines = -kPageLines;
- break;
- case inPageDown:
- lines = kPageLines;
- break;
- default:
- return;
- }
-
- if ((ctlValue+lines)>ctlMax)
- lines = ctlMax-ctlValue;
- if ((ctlValue+lines)<ctlMin)
- lines = ctlMin-ctlValue;
-
- if (lines!=0) {
- ScrollText(theDialog,lines);
- SetCtlValue(theControl,ctlValue+lines);
- }
- }
-
-
- /* sets the text top line to be the same as the current scrollbar position. this is called after
- a thumb movement in the scrollbar.
- */
-
- void ReAlignTextToScrollbar(DialogPtr theDialog)
- {
- TEHandle theTE;
- ControlHandle scrollBar;
- short controlScrollPosition,textScrollPosition,scrollDelta,scrollPix;
-
- theTE = GetTEHandle(theDialog);
- scrollBar = GetScrollBar(theDialog);
-
- controlScrollPosition = GetCtlValue(scrollBar);
- textScrollPosition = ((**theTE).viewRect.top - (**theTE).destRect.top) / (**theTE).lineHeight;
- scrollDelta = textScrollPosition - controlScrollPosition;
- scrollPix = scrollDelta * (*theTE)->lineHeight;
- TEScroll(0,scrollPix,theTE);
- }
-
-
- /* sets the scrollbar thumb to the current text position. this is called after autoscrolling,
- which may occur after a call to TEKey, or during a drag-scroll
- */
-
- void ReAlignScrollbarToText(DialogPtr theDialog)
- {
- TEHandle theTE;
- ControlHandle scrollBar;
- short textScrollPosition;
-
- theTE = GetTEHandle(theDialog);
- scrollBar = GetScrollBar(theDialog);
-
- textScrollPosition = ((**theTE).viewRect.top - (**theTE).destRect.top) / (**theTE).lineHeight;
- SetCtlValue(scrollBar,textScrollPosition);
- }
-
-
- /* scrolls the text by the delta passed in to the function. called in response to clicking the
- arrows or page areas of the scrollbar to move the text
- */
-
- void ScrollText(DialogPtr theDialog,short lines)
- {
- TEHandle theTE;
- short scrollPix;
- short textScrollPosition;
-
- theTE = GetTEHandle(theDialog);
-
- textScrollPosition = ((**theTE).viewRect.top - (**theTE).destRect.top) / (**theTE).lineHeight;
- if ((textScrollPosition+lines)<0)
- lines = -textScrollPosition;
- if ((textScrollPosition+lines)>kMaxLines)
- lines = kMaxLines-textScrollPosition;
-
- scrollPix = lines * (*theTE)->lineHeight;
-
- TEScroll(0,-scrollPix,theTE);
- }
-
-
- /* text drag callback procedure. this routine handles drag scrolling by checking to see if we
- are in the area where drag-scrolling is necessary, and calling scrolltext followed by a
- scrollbar realignment
- */
-
- pascal Boolean MyTEClickProc(void)
- {
- Point pt;
- DialogPtr theDialog;
- ControlHandle theControl;
- TEHandle theTE;
- Rect textRect;
- short scrollLines;
- GrafPtr savePort;
- RgnHandle saveClip;
-
- GetMouse(&pt);
- theDialog = (DialogPtr)FrontWindow();
- theTE = GetTEHandle(theDialog);
-
- GetPort(&savePort);
- SetPort(theDialog);
-
- saveClip = NewRgn();
- GetClip(saveClip);
- ClipRect(&theDialog->portRect);
-
- scrollLines = 0;
- textRect = (**theTE).viewRect;
- if (pt.v < textRect.top)
- scrollLines = -1;
- else if (pt.v > textRect.bottom)
- scrollLines = 1;
-
- if (scrollLines) {
- ScrollText(theDialog,scrollLines);
- ReAlignScrollbarToText(theDialog);
- }
-
- SetClip(saveClip);
- DisposHandle(saveClip);
- SetPort(savePort);
- return true;
- }
-
-
- /* utility procedure to return a handle to the scrollbar control
- */
-
- ControlHandle GetScrollBar(DialogPtr theDialog)
- {
- ControlHandle theScroller;
- short iType;
- Rect iRect;
-
- GetDItem(theDialog,kScrollerItem,&iType,&theScroller,&iRect);
- return theScroller;
- }
-
-
- /* utility procedure to return the textedit record for the given dialog */
-
- TEHandle GetTEHandle(DialogPtr theDialog)
- {
- return( (TEHandle)GetWRefCon((WindowPtr)theDialog) );
- }